using Quartz;
using Vin.Extension.Framework.Base;
using Vin.Extension.Framework.Quartz.Dto.Entities;
using Vin.Extension.Framework.Quartz.Entities;
using Vin.Extension.Framework.Quartz.Jobs;
using Vin.Extension.Framework.Quartz.Models;
using Vin.Extension.Framework.Quartz.ServiceInterface;
using Vin.Tool.Attributes;
using Vin.Tool.Core.DateTimeCategory;
using Vin.Tool.Enums;

namespace Vin.Extension.Framework.Quartz.Service;

[Service(Lifetime = Lifetime.Singleton)]
public class VinJobService : VinFrameworkBaseService, IVinJobService
{
    [Inject] private readonly ISysJobService _sysJobService = null!;

    public async Task<bool> AddAsync<T>(string redisJobMapKey, string businessId, JobInfo jobInfo) where T : VinBaseJob
    {
        // 添加定时任务
        var oldJobId = await RedisCache.GetHashCacheAsync<long?>(redisJobMapKey, businessId);
        if (oldJobId.HasValue)
        {
            // 移出旧的任务
            await DelAsync(oldJobId.Value);
        }

        // 添加新的任务
        var jobId = await StartAsync<T>(jobInfo);
        // 添加到缓存
        await RedisCache.SetHashCacheAsync(redisJobMapKey, businessId, jobId.ToString());

        return true;
    }

    public async Task<bool> RemoveAsync(string redisJobMapKey, string businessId)
    {
        // 停止并删除任务
        var oldJobId = await RedisCache.GetHashCacheAsync<long?>(redisJobMapKey, businessId);
        if (oldJobId.HasValue)
        {
            await StopAsync(oldJobId.Value);
            await DelAsync(oldJobId.Value);
        }
        
        // 从缓存中移除
        await RedisCache.RemoveHashCacheAsync(redisJobMapKey, businessId);

        return true;
    }

    public async Task<long> StartAsync(JobInfo info)
    {
        var job = await AddJobAsync(info);
        if (job == null) return 0;

        long jobId = job.Id!.Value;

        // 启动任务
        await _sysJobService.StartAsync(jobId);

        return jobId;
    }

    public async Task<long> StartAsync(string name, string groupName, Dictionary<string, string>? parameters = null)
    {
        return await StartAsync(new JobInfo(name, groupName, parameters));
    }

    public async Task<long> StartAsync<T>(JobInfo info) where T : IJob
    {
        info.ClassName = typeof(T).FullName;
        return await StartAsync(info);
    }

    public async Task<long> StartAsync<T>(string name, string groupName, Dictionary<string, string>? parameters = null)
        where T : IJob
    {
        return await StartAsync<T>(new JobInfo(name, groupName, parameters));
    }

    public async Task<bool> StopAsync(long id)
    {
        var job = await _sysJobService.QueryAsync(id);
        if (job == null) return false;

        // 停止任务
        await _sysJobService.StopAsync(id);

        return true;
    }

    public async Task<bool> DelAsync(long id)
    {
        var job = await _sysJobService.QueryAsync(id);
        if (job == null) return false;

        // 删除任务
        await _sysJobService.DelAsync(id);

        return true;
    }

    private async Task<SysJobDto?> AddJobAsync(JobInfo info)
    {
        var job = new SysJobDto()
        {
            Name = info.Name,
            GroupName = info.GroupName,
            ExecuteType = info.ExecuteType,
            AssemblyPath = info.AssemblyPath,
            AssemblyName = info.AssemblyName,
            ClassName = info.ClassName,
            Parameters = info.Parameters.Select(m => new JobParams()
            {
                Key = m.Key,
                Value = m.Value
            }).ToList(),
            FirstExecute = info.FirstExecute,
            StartTime = info.StartTime?.ToTimestamp(false),
            EndTime = info.EndTime?.ToTimestamp(false),
            TriggerType = info.TriggerType,
            LoopType = info.LoopType,
            LoopCount = info.LoopCount,
            IntervalType = info.IntervalType,
            IntervalValue = info.IntervalValue,
            Cron = info.Cron,
        };
        return await _sysJobService.SaveReturnDataAsync(job);
    }
}